/**
 * Created by billy on 2020/6/29.
 */
var htmlPrase = require("htmlparser2");

var formTags = {
	input: null,
	option: null,
	optgroup: null,
	select: null,
	button: null,
	datalist: null,
	textarea: null,
	output: null,
};
var openImpliesClose = {
	tr: null,
	th: null,
	td: null,
	thead: null,
	ul: null,
	li: null,
	p: null,
	span: null,
	strong: require("./tag-creator/strong"),
	h1: require("./tag-creator/h"),
	h2: require("./tag-creator/h"),
	h3: require("./tag-creator/h"),
	h4: require("./tag-creator/h"),
	h5: require("./tag-creator/h"),
	h6: require("./tag-creator/h"),
	section: require("./tag-creator/section"),
	article: require("./tag-creator/section"),
	figure: require("./tag-creator/section"),
	div: require("./tag-creator/div"),
	main: require("./tag-creator/section"),
	figcaption: require("./tag-creator/section"),
	blockquote: null,
};
var voidElements = {
	__proto__: null,
	area: null,
	base: null,
	basefont: null,
	br: require("./tag-creator/br"),
	col: null,
	command: null,
	embed: null,
	frame: null,
	hr: null,
	img: require("./tag-creator/img"),
	input: null,
	isindex: null,
	keygen: null,
	link: null,
	meta: null,
	param: null,
	source: null,
	track: null,
	wbr: null
};
var disableElements = {
	math: null,
	svg: null,
	header: null,
	link: null,
	style: null,
	mpvoice: null,
};

var htmlIntegrationElements = {
	__proto__: null,
	mi: true,
	mo: true,
	mn: true,
	ms: true,
	mtext: true,
	"annotation-xml": true,
	foreignObject: true,
	desc: true,
	title: true
};

var Tag = {
	formTags,
	openImpliesClose,
	voidElements,
	disableElements,
	htmlIntegrationElements
}

var ElementType = {
	Text: "text", //Text
	Directive: "directive", //<? ... ?>
	Comment: "comment", //<!-- ... -->
	Script: "script", //<script> tags
	Style: "style", //<style> tags
	Tag: "tag", //Any tag
	CDATA: "cdata", //<![CDATA[ ... ]]>
	Doctype: "doctype",

	isTag: function (elem)
	{
		return elem.type === "tag" || elem.type === "script" || elem.type === "style";
	}
};

function createHtml($tree, $type = "view")
{
	var html = "";
	for (var nodeItem of $tree)
	{
		html += getHtml_node(nodeItem, $type);
//		if(nodeItem.data)
//		{
//			trace(nodeItem.data)
//		}
	}
	return html;
}
function getHtml_node(node, $type = "view")
{
	if (node.type == ElementType.Text)
	{	//文本node,返回文本
		return node.data
			.replace(/&/g, "&amp;")
			.replace(/>/g, "&gt;")
			.replace(/</g, "&lt;")
	}
	else if (node.type == ElementType.Tag)
	{
		//标签node
		var tagName = node.name;
		if (node.attribs.style)
		{
			if (node.attribs.style.match(/display: *none/g))
			{
				return "";
			}
		}
		if (tagName in Tag.voidElements)
		{
			//独立标签
			return Tag.voidElements[tagName] ?
				Tag.voidElements[tagName](node, createAttribs, createHtml, $type) :
				`<${tagName}${createAttribs(node, $type)}>`
		}
		else if (tagName in Tag.openImpliesClose)
		{
			return Tag.openImpliesClose[tagName] ?
				Tag.openImpliesClose[tagName](node, createAttribs, createHtml, $type) :
				`<${tagName}${createAttribs(node, $type)}>${createHtml(node.children, $type)}</${tagName}>`
		}
		else if (tagName in Tag.disableElements)
		{
			return "";
		}
		else if (tagName in Tag.formTags)
		{
			return "";
		}
		else
		{
			return `<${tagName}${createAttribs(node, $type)}>${createHtml(node.children, $type)}</${tagName}>`;
		}
	}
	else
	{
		return "";
	}
}

function createAttribs($node, $type)
{
	var attribs = $node.attribs;
	if (attribs.style)
	{
		attribs.style = styleFilter(attribs.style);
	}
	var attStr = Object.keys(attribs)
		.filter(v=>attribsFilter(attribs, v, $type))
		.map(v=>`${v}="${converCharacter(v, attribs[v])}"`)
		.join(" ");

	attStr = trim(attStr);
	if (attStr)
	{
		attStr = " " + attStr;
	}
	return attStr;
}

function converCharacter($key, $char)
{
	if ($key == "href")
	{
		return $char
			.replace(/&amp;/g, "=【】=")
			.replace(/&/g, "&amp;")
			.replace(/=【】=/g, "&amp;")
	}
//	return $char
//		.replace(/&/g, "&amp;")

	return $char
		.replace(/&amp;/g, "&")
		.replace(/&gt;/g, ">")
		.replace(/&lt;/g, "<")
}

var _attribsFilters = [{
	name: "data-",
	rule: "prefix"
}, {
	name: "data_",
	rule: "prefix"
}, {
	name: "powered-by",
	rule: "equal"
}, {
	name: "label",
	rule: "equal"
}, {
	name: "line",
	rule: "equal"
}, {
	name: "aria-",
	rule: "prefix"
}, {
	name: "version",
	rule: "equal"
}]
function attribsFilter($attribs, $attribName, $type)
{
	if (!$attribs[$attribName])
	{
		return false;
	}
//	var list = $type == "view" || true ? _attribsFilters : _attribsFilters.concat([{
//		name: "style",
//		rule: "equal",
//	}])
	var list = _attribsFilters;
	return list.every(v=>
	{
		if (v.hasOwnProperty("enable") && v.enable === false)
		{
			return true;
		}
		if (v.rule == "equal")
		{
			return v.name != $attribName;
		}
		else if (v.rule == "prefix")
		{
			return $attribName.indexOf(v.name) < 0;
		}
	})
}

function styleFilter($style)
{
	$style = trim($style);
	$style = $style.replace(/&quot;/g, "\"");
	var styleList = $style.split(";").filter(v=>
	{
		v = trim(v);
		return v != ""
			&& v.indexOf("font-family:") < 0
			&& v.indexOf("url(") < 0
			&& v.indexOf("background-image:") < 0
			&& v.indexOf("z-index:") < 0
			&& v.indexOf("background-repeat") < 0
			&& v.indexOf("visibility") < 0
			&& v.indexOf("letter-spacing:") < 0
	});
	return styleList.join(";");
}

function formatHtml($html)
{
	var tagName = ""
	var offsetIndex = 0;
	$html = trim($html);
//	$html = $html.replace(/\xa0/g, "&nbsp;");
	$html = $html.substring($html.indexOf("<"), $html.lastIndexOf(">") + 1);
//	$html = "<section style='color:red'/>";
//	trace($html.length)
//	trace($html.substr(52270))
	if ($html.indexOf("<") < 0)
	{
		return $html;
	}
	while (offsetIndex < $html.length && offsetIndex >= 0)
	{
		offsetIndex = $html.indexOf("<", offsetIndex);
		var endTagIndex = $html.indexOf(">", offsetIndex);
		if ($html.charAt(endTagIndex - 1) == "/" && offsetIndex + 1 != endTagIndex)
		{
			var endIndex = $html.indexOf(" ", offsetIndex);
			if (endIndex < 0)
			{
				endIndex = endTagIndex - 1;
			}
			else
			{
				endIndex = Math.min(endIndex, endTagIndex - 1);
			}
			var tagName = $html.substring(offsetIndex + 1, endIndex);
			if (!voidElements[tagName])
			{
				$html = $html.substring(0, endTagIndex - 1) + `></${tagName}>` + $html.substring(endTagIndex + 1);
				offsetIndex = endTagIndex + 3 + tagName.length;
			}
			else
			{
				offsetIndex = endTagIndex + 1;
			}
		}
		else
		{
			offsetIndex = endTagIndex + 1;
		}
	}
	return $html;
}

exports.format = function ($html, $type = "view")
{
	$html = formatHtml($html);
	var tree = htmlPrase.parseDOM($html);
	var html = createHtml(tree, $type);
	html = html.replace(/<br><\/br>/g, "<br>");
	while (html.indexOf("<br><br>") >= 0)
	{
		html = html.replace("<br><br>", "<br>");
	}
	html = html.replace(/\xa0/g, "&nbsp;");
//	html = html.replace(/&gt;/g, ">");
//	html = html.replace(/&lt;/g, "<");
//	html = html.replace(/&amp;/g, "&");
	return html;
}

exports.parse = function ($html)
{
	var tree = htmlPrase.parseDOM($html);
	return {
		tree,
		html: createHtml(tree)
	};
}
